var Imported = Imported || {};
Imported.JIA_EquipSlots = true;

var Wefjia = Wefjia || {};
Wefjia.EquipSlots = Wefjia.EquipSlots || {};
Wefjia.EquipSlots.version = 2.10;

/*:
 * @plugindesc V2.10 允许防具装备到多个不同类型的装备槽位。
 * @author Wefjia
 * 
 * @param setting slots for a class
 * @text 允许为一整类物品设置可装备槽位
 * @type boolean
 * @default false
 * 
 * @param clsList
 * @parent Setting Slots for a class
 * @text 类型槽位设置
 * @type struct<cls>[]
 * 
 * @help
 * !!!注意，本插件有大概率和其它有改动变更装备相关功能的插件冲突
 * !!!如果加载本插件后使某个插件不生效请尝试让本插件先行加载, 如不能解决只能放弃其中一个的使用或者自行尝试合并插件
 * 
 * 这个插件解除了一个类型装备只能装在同一个槽位的限制(左右手饰品位可以实现了)。
 * 
 * 你可以开启插件设置中的允许为一整类物品设置可装备槽位并设置类型槽位设置来实现一整类物品的设置
 * 
 * 也可以
 * 在数据库中的防具备注栏中使用以下标签来进行单个物品的设置, 单独设置的优先级高于整理设置：
 * <EquipSlots:x,y,z>
 * 其中，x,y,z 是装备类型的ID，用逗号分隔。
 *
 * 例如，如果你想让一个防具能够装备到装备类型槽位 3 和 4，可以使用以下标签：
 * <EquipSlots:3,4>
 * 
 * url: https://gitee.com/Alpha_fjh/mv-plugins;
 */

/*~struct~cls:
 * @param clsId
 * @text 要替换类型的id
 * @type number
 * 
 * @param soltIds
 * @text 允许的槽位id列表
 * @type number[]
 */

Wefjia.EquipSlots.setupParameters = function () {
    let ES = Wefjia.EquipSlots;
    ES.Parameters = PluginManager.parameters('JIA_EquipSlots');
    ES.Param = ES.Param || {};

    ES.Param.cls2solt = Boolean(ES.Parameters['setting slots for a class']);
    if (ES.Param.cls2solt) {
        ES.Parameters.clsList = ES.Parameters.clsList
            .replace(/\\"/g, '"')
            .replace(/\\\\"/g, '')
            .replace(/"{/g, '{')
            .replace(/"}"/g, '}')
            .replace(/:"/g, ':')
            .replace(/",/g, ',');
        ES.Param.clsList = JSON.parse(ES.Parameters.clsList);
    }
};
Wefjia.EquipSlots.setupParameters();

(function () {
    const Util = {
        getSlots: function (item) {
            if (ES._loaded_JIA_EquipSlots) {
                return item.equipSlots;
            }
            return item.meta.EquipSlots ? item.meta.EquipSlots.split(',').map(Number) : [item.etypeId];
        },
        isAllowEquip: function (slotId, item) {
            return this.getSlots(item).includes(slotId);
        },
        processNotetag: function (data, clsList) {
            let map = {};
            for (let i = 0; i < clsList.length; ++i) {
                map[clsList[i].clsId] = clsList[i].soltIds;
            }
            for (let i = 1; i < data.length; i++) {
                const equip = data[i];
                if (equip.meta.EquipSlots) {
                    equip.equipSlots = this.getSlots(equip);
                    continue;
                }

                equip.equipSlots = map[equip.etypeId] ? map[equip.etypeId] : [equip.etypeId];
            }
        }
    };

    const ES = Wefjia.EquipSlots;

    ES.DataManager_isDatabaseLoaded = DataManager.isDatabaseLoaded;
    DataManager.isDatabaseLoaded = function () {
        if (!ES.DataManager_isDatabaseLoaded.call(this)) return false;
        if (ES.Param.cls2solt && !ES._loaded_JIA_EquipSlots) {
            Util.processNotetag($dataWeapons, ES.Param.clsList);
            Util.processNotetag($dataArmors, ES.Param.clsList);
            ES._loaded_JIA_EquipSlots = true;
        }
        return true;
    };

    Game_Actor.prototype.changeEquip = function (slotId, item) {
        if (this.tradeItemWithParty(item, this.equips()[slotId]) &&
            (!item || Util.isAllowEquip(this.equipSlots()[slotId], item))) {
            this._equips[slotId].setObject(item);
            this.refresh();
        }
    };

    Game_Actor.prototype.releaseUnequippableItems = function (forcing) {
        for (; ;) {
            var slots = this.equipSlots();
            let equips = this.equips();
            let changed = false;
            for (let i = 0; i < equips.length; i++) {
                let item = equips[i];
                if (item && (!this.canEquip(item) || !Util.isAllowEquip(slots[i], item))) {
                    if (!forcing) {
                        this.tradeItemWithParty(null, item);
                    }
                    this._equips[i].setObject(null);
                    changed = true;
                }
            }
            if (!changed) {
                break;
            }
        }
    };

    Window_EquipItem.prototype.includes = function (item) {
        if (item === null) {
            return true;
        }
        if (this._slotId < 0 || !Util.isAllowEquip(this._actor.equipSlots()[this._slotId], item)) {
            return false;
        }
        return this._actor.canEquip(item);
    };

    Game_Actor.prototype.bestEquipItem = function(slotId) {
        var etypeId = this.equipSlots()[slotId];
        var items = $gameParty.equipItems().filter(function(item) {
            return Util.isAllowEquip(etypeId, item) && this.canEquip(item);
        }, this);
        var bestItem = null;
        var bestPerformance = -1000;
        for (var i = 0; i < items.length; i++) {
            var performance = this.calcEquipItemPerformance(items[i]);
            if (performance > bestPerformance) {
                bestPerformance = performance;
                bestItem = items[i];
            }
        }
        return bestItem;
    };
})();
